#ifndef _VEC6222011_H_
#define _VEC6222011_H_

template <class Raw>
class Vector: public Raw
{
public:
 	typedef typename Raw::Type Type;
public:
	Vector() {}

	Vector(Type _x, Type _y):
		Raw(_x, _y) {}

	Vector(Type _x, Type _y, Type _z):
		Raw(_x, _y, _z) {}

	Vector(Type _x, Type _y, Type _z, Type _w):
		Raw(_x, _y, _z, _w) {}

	Vector(const Type* buf) {
		for (int i = 0; i < Raw::DEMENSION; i ++) {
			data[i] = buf[i];
		}
		adjust();
	}

	Vector(const Raw& p) {
		for (int i = 0; i < Raw::DEMENSION; i ++) {
			data[i] = p.data[i];
		}
		adjust();
	}

	Vector(const Vector& p) {
		for (int i = 0; i < Raw::DEMENSION; i ++) {
			data[i] = p.data[i];
		}
		adjust();
	}

	Type getPointer() const {
		return data;
	}

	Vector operator+(const Vector& p) const {
		Vector r;
		for (int i = 0; i < DEMENSION; i ++) {
			r.data[i] = this->data[i]/this->factor() + p.data[i]/p.factor();
		}
		r.adjust();
		return r;
	}

	void operator+=(const Vector& p) {
		*this = this->operator+(p);
	}

	Vector operator-(const Vector& p) const {
		Vector r;
		for (int i = 0; i < DEMENSION; i ++) {
			r.data[i] = data[i]/factor() - p.data[i]/p.factor();
		}
		r.adjust();
		return r;
	}

	void operator-=(const Vector& p) {
		*this = this->operator-(p);
	}

	Vector operator*(Type p) const {
		Vector r;
		for (int i = 0; i < DEMENSION; i ++) {
			r.data[i] = data[i] * p;
		}
		r.adjust();
		return r;
	}

	void operator*=(Type p) {
		*this = this->operator*(p);
	}
};

template <class Raw>
class SpaceVector: public Vector<Raw> {
public:
	typedef typename Vector::Type Type;
public:
	SpaceVector() {}

	SpaceVector(Type _x, Type _y):
	Vector(_x, _y) {}

	SpaceVector(Type _x, Type _y, Type _z):
	Vector(_x, _y, _z) {}

	SpaceVector(Type _x, Type _y, Type _z, Type _w):
	Vector(_x, _y, _z, _w) {}

	SpaceVector(const Type* buf) {
		for (int i = 0; i < DEMENSION; i ++) {
			data[i] = buf[i];
		}
		adjust();
	}

	SpaceVector(const Vector& p) {
		for (int i = 0; i < DEMENSION; i ++) {
			data[i] = p.data[i];
		}
		adjust();
	}

	SpaceVector(const SpaceVector& p) {
		for (int i = 0; i < DEMENSION; i ++) {
			data[i] = p.data[i];
		}
		adjust();
	}

	SpaceVector dot(const SpaceVector& p) const {
		Type r = 0;
		Type fac = factor() * r.factor();
		for (int i = 0; i < DEMENSION; i ++) {
			r += p.data[i] * data[i] / fac;
		}
		r.adjust();
		return r;
	}
};
#endif // _VEC6222011_H_